<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script>
  const html = `
  <div class="container">
    <header class="header" id="header">
      <nav>
        <li><a href="http://ssss.com">menu home home home</a></li>
        <li><a href="http://ssss.com">  menu user</a></li>
      </nav>
    </header>
    <main>
      <  section  >
        <ul>
          <li>select 1</li>
          <li>  select 2</li>
          <li>select 3  </li>
          <li>  select 3  </li>
        </ul>
      </section>
      <article>
        <img src="https://image.jpg" /  >
        <div>
          some text
        </div>
      </article>
    <  /  main>
    <footer>
      footer
    </footer>
  </div>
  `

  function findTag (str) {
    if (str.trim().length) {
      return str.trim().match(/[a-zA-Z]+/)[0]
    }
  }

  const tags = []
  const parents = []

  html.replace(/<[^>]+>|((?<=[^<]).+?(?=<))/gms, (substring) => {
    const tag = findTag(substring)
    if (!tag) return;
    const tagId = Math.abs(Math.random() * Math.pow(10, 10))

    substring = substring.replace(/<\s*/, '<')
    substring = substring.replace(/\s*>/, '>')

    if (substring.startsWith('</')) {
      substring = substring.replace(/<\/\s*/, '<\/')
    }

    if (substring.startsWith('</')) {
      parents.pop()
      return substring
    }

    const node = {
      id: tagId,
      tag, node: substring, children: []
    }

    const __parents = [...parents]
    const parentNode = __parents.pop()

    if (parentNode) {
      node.parentId = parentNode.id
      node.parentNode = parentNode
    }

    if (substring.startsWith('<')) {
      node.type = 'element'

      if (substring.endsWith('/>') || substring.startsWith('<img')) {
      } else {
        parents.push(node)
      }
    } else {
      node.type = 'text'
    }

    tags.push(node)

    return substring
  })

  // 解析后的数组
  console.log(tags)

  let tree = {}

  while (tags.length > 0) {
    const item = tags.shift()
    const hasChild = tags.find(child => item.id === child.parentId)

    if (hasChild) {
      tags.push(item)
    } else {
      if (tree[item.id]) {
        item.children = tree[item.id]
        delete tree[item.id]
      }

      if (item.parentId) {
        tree[item.parentId] = tree[item.parentId] || []
        tree[item.parentId].push(item)
      } else {
        tree.root = item
      }
    }
  }

  // 解析后的数组 重新构造为 【树形结构】
  console.log(tree)
</script>
</body>
</html>
